Skip to content

feat: Better parsing of external HTML attributes & inline styles #1605

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

matthewlipski
Copy link
Collaborator

@matthewlipski matthewlipski commented Apr 11, 2025

This PR adds tests for parsing various HTML attributes & inline styles, and provides fixes so that these tests pass. Namely, these tests include:

  • Parsing numbered list start props from start attribute.
  • Parsing image width props from width attribute.
  • Parsing bold, italic, underline, and strike marks from various tags & inline styles. This includes e.g. b tags and font-weight inline styles for bold marks as well as i tags and font-style inline styles for italic marks.
  • Parsing textColor and backgroundColor marks from inline styles.
  • Parsing textColor and backgroundColor props from inline styles.
  • Parsing textAlignment props from inline styles.

To ensure all tests pass, several changes have also been made to the code:

  • Parse rules have been added to textColor, backgroundColor, and textAlignment` props for inline styles.
  • The textColor and backgroundColor props have been changed, so that they're now applied as attributes to blockContent nodes instead of blockContainer nodes. This is because we would only attempt to parse these props when a blockContainer node is found, i.e. when a div with [data-node-type="blockContainer"] is found. So we would never even attempt to parse these props from external HTML. The CSS has been updated also to account for this change. Also, all other block props are already stored on the blockContent node, so this makes the textColor and backgroundColor props also consistent with that.
  • Small fixes have been made to numbered list item and quote blocks.

Additionally, code for color props & marks has been cleaned up slightly.

The large negative diff in this PR is also because a bunch of redundant React unit test snapshots have been removed.

Copy link

vercel bot commented Apr 11, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
blocknote ✅ Ready (Inspect) Visit Preview Apr 23, 2025 8:10pm
blocknote-website ✅ Ready (Inspect) Visit Preview Apr 23, 2025 8:10pm

Copy link

pkg-pr-new bot commented Apr 11, 2025

Open in StackBlitz

@blocknote/ariakit

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/ariakit@1605

@blocknote/code-block

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/code-block@1605

@blocknote/core

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/core@1605

@blocknote/react

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/react@1605

@blocknote/mantine

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/mantine@1605

@blocknote/server-util

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/server-util@1605

@blocknote/shadcn

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/shadcn@1605

@blocknote/xl-docx-exporter

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/xl-docx-exporter@1605

@blocknote/xl-multi-column

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/xl-multi-column@1605

@blocknote/xl-odt-exporter

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/xl-odt-exporter@1605

@blocknote/xl-pdf-exporter

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/xl-pdf-exporter@1605

commit: ab09848

Copy link
Contributor

@nperez0111 nperez0111 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 this looks exactly as I'd have expected it to.

Great work @matthewlipski

Base automatically changed from unit-tests-setup to main April 17, 2025 08:20
"data-background-color": attributes.stringValue,
}),
},
stringValue: getBackgroundColorAttribute("stringValue"),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this loses default: undefined, not sure if intended

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't really make a difference, there's not really a use case where you would set a color mark with a default value. Selecting a default text/bg color in the color picker removes the mark instead, and this is how it should always be done, so the default value for the mark should never be used.

if (element.hasAttribute("data-text-color")) {
return { stringValue: element.getAttribute("data-text-color") };
if (element.hasAttribute("data-text-color") || element.style.color) {
return {};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return {}?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we don't need to parse the color because it's already handled in the parseHTML function of the stringValue attribute.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't we omit line 25 / 26 then entirely? it's still a bit confusing right? (maybe tiptap issue)

@matthewlipski matthewlipski changed the title feat: Less data loss in external HTML feat: Better parsing of HTML attributes & inline styles Apr 23, 2025
@matthewlipski matthewlipski changed the title feat: Better parsing of HTML attributes & inline styles feat: Better parsing of external HTML attributes & inline styles Apr 24, 2025
Copy link
Collaborator

@YousefED YousefED left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

Just realized one caveat; for yjs stored documents the block color data will probably be lost when upgrading (or the document might break entirely, but I doubt that).

Perhaps you can see with Nick if there's a fix for that possible (or a migration path for people upgrading)

<div class="bn-block-column-list" data-node-type="columnList" data-id="1" style="display: flex;"><div class="bn-block-column" data-node-type="column" data-id="2" data-width="1" style="flex-grow: 1;"><p>Column Paragraph 0</p><p>Column Paragraph 1</p></div><div class="bn-block-column" data-node-type="column" data-id="5" data-width="1" style="flex-grow: 1;"><p>Column Paragraph 2</p><p>Column Paragraph 3</p></div></div>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any idea why this snapshot is a lot smaller while the other ones got larger?

background-color: #f4dfeb;
}

/* TEXT ALIGNMENT */
[data-text-alignment="left"] {
justify-content: flex-start !important;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you know why this was here / why has it been removed?


export const BackgroundColorExtension = Extension.create({
name: "blockBackgroundColor",

addGlobalAttributes() {
return [
{
types: ["blockContainer", "tableCell", "tableHeader"],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose not, but does this break anything for colors / alignment on custom blocks (as you're changing this from blockcontainer to explicitly naming the block types)


export const TextColorExtension = Extension.create({
name: "blockTextColor",

addGlobalAttributes() {
return [
{
types: ["blockContainer", "tableCell", "tableHeader"],
types: [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question as above; does this break anything for custom blocks?

if (element.hasAttribute("data-text-color")) {
return { stringValue: element.getAttribute("data-text-color") };
if (element.hasAttribute("data-text-color") || element.style.color) {
return {};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't we omit line 25 / 26 then entirely? it's still a bit confusing right? (maybe tiptap issue)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants